package com.jch.definition;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.charset.StandardCharsets;
import java.util.List;

// 自定义解码器: 解码处理，整包数据、半包数据、沾包数据
public class DefinitionDecoder extends ByteToMessageDecoder {

    // 数据包基础长度
    private final int BASE_LENGTH = 4;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

        // 判断基础长度
        if (in.readableBytes() < BASE_LENGTH){
            return;
        }

        // 记录包头位置
        int beginIdx;

        while(true){
            // 获取包头开始的index
            beginIdx = in.readerIndex();
            // 标记包头
            in.markReaderIndex();
            // 读到协议的开始标志，结束while循环
            if (in.readByte() == 0x02){
                break;
            }
            // 未读到包头，略过一个字节；每次略过一个字节读取包头信息,并标记
            in.resetReaderIndex();
            in.readByte();
            // 当略过一个字节后，数据包长度，又不满足基础长度，则此时应当结束。并等待后面的数据到达。
            if (in.readableBytes() < BASE_LENGTH){
                return;
            }
        }

        //判断剩余长度不足可读取数量【没有内容长度】
        int readableCount = in.readableBytes();
        if (readableCount <= 1){
            in.readerIndex(beginIdx); // 标记读取位置
            return;
        }

        // 长度 占 4个字节，读取int
        ByteBuf byteBuf = in.readBytes(1);
        String msgLengthStr = byteBuf.toString(StandardCharsets.UTF_8);
        int msgLength = Integer.parseInt(msgLengthStr);

        // 判断剩余长度，不足可读数量【没有结尾标识】
        readableCount = in.readableBytes();
        if (readableCount < msgLength + 1){
            in.readerIndex(beginIdx);
            return;
        }
        ByteBuf msgContent = in.readBytes(msgLength);

        // 若没有结尾标识，还原指针位置【其他标识结尾】
        byte end = in.readByte();
        if (end != 0x03){
            in.readerIndex(beginIdx);
            return;
        }
        out.add(msgContent.toString(StandardCharsets.UTF_8));
    }
}
